aboutsummaryrefslogtreecommitdiff
path: root/src/routes/user/[user]
diff options
context:
space:
mode:
Diffstat (limited to 'src/routes/user/[user]')
-rw-r--r--src/routes/user/[user]/+page.gql30
-rw-r--r--src/routes/user/[user]/+page.svelte334
-rw-r--r--src/routes/user/[user]/+page.ts32
-rw-r--r--src/routes/user/[user]/badges/+page.gql54
-rw-r--r--src/routes/user/[user]/badges/+page.svelte857
-rw-r--r--src/routes/user/[user]/badges/+page.ts34
6 files changed, 696 insertions, 645 deletions
diff --git a/src/routes/user/[user]/+page.gql b/src/routes/user/[user]/+page.gql
index 491290aa..fd31248b 100644
--- a/src/routes/user/[user]/+page.gql
+++ b/src/routes/user/[user]/+page.gql
@@ -1,18 +1,18 @@
query Profile($id: Int!) {
- User(id: $id) {
- id
- badgesCount
+ User(id: $id) {
+ id
+ badgesCount
- preferences {
- created_at
- updated_at
- user_id
- pinned_hololive_streams
- hide_missing_badges
- biography
- badge_wall_css
- hide_awc_badges
- pinned_badge_wall_categories
- }
- }
+ preferences {
+ created_at
+ updated_at
+ user_id
+ pinned_hololive_streams
+ hide_missing_badges
+ biography
+ badge_wall_css
+ hide_awc_badges
+ pinned_badge_wall_categories
+ }
+ }
}
diff --git a/src/routes/user/[user]/+page.svelte b/src/routes/user/[user]/+page.svelte
index 3c581c38..fd1e2d7e 100644
--- a/src/routes/user/[user]/+page.svelte
+++ b/src/routes/user/[user]/+page.svelte
@@ -1,36 +1,49 @@
<script lang="ts">
- import Spacer from '$lib/Layout/Spacer.svelte';
- import settings from '$stores/settings';
- import ParallaxImage from '../../../lib/Image/ParallaxImage.svelte';
- import { typeSchedule, type ParseResult } from '$lib/Hololive/hololive';
- import HeadTitle from '$lib/Home/HeadTitle.svelte';
- import Message from '$lib/Loading/Message.svelte';
- import { estimatedDayReading } from '$lib/Media/Manga/time';
- import Skeleton from '$lib/Loading/Skeleton.svelte';
- import root from '$lib/Utility/root';
- import locale from '$stores/locale';
- import { onMount } from 'svelte';
- import authorisedUsers from '$lib/Data/Static/authorised.json';
- import tooltip from '$lib/Tooltip/tooltip';
- import AnimeRateLimited from '$lib/Error/AnimeRateLimited.svelte';
- import identity from '$stores/identity';
- import SettingHint from '$lib/Settings/SettingHint.svelte';
- import proxy from '$lib/Utility/proxy';
- import { parseScheduleHtml } from '$lib/Data/hololive';
- import type { Preferences } from '../../../graphql/$types';
- import SvelteMarkdown from '@humanspeak/svelte-markdown';
- import MarkdownLink from '$lib/MarkdownLink.svelte';
- import LinkedTooltip from '$lib/Tooltip/LinkedTooltip.svelte';
- import { graphql } from '$houdini';
-
- export let data;
-
- $: ({ Profile } = data);
- $: preferences = $Profile.fetching
- ? undefined
- : ($Profile.data?.User?.preferences as Preferences | undefined);
-
- const setCategoriesQuery = graphql(`
+import Spacer from "$lib/Layout/Spacer.svelte";
+import settings from "$stores/settings";
+import ParallaxImage from "../../../lib/Image/ParallaxImage.svelte";
+import { typeSchedule, type ParseResult } from "$lib/Hololive/hololive";
+import HeadTitle from "$lib/Home/HeadTitle.svelte";
+import Message from "$lib/Loading/Message.svelte";
+import { estimatedDayReading } from "$lib/Media/Manga/time";
+import Skeleton from "$lib/Loading/Skeleton.svelte";
+import root from "$lib/Utility/root";
+import locale from "$stores/locale";
+import { onMount } from "svelte";
+import authorisedUsers from "$lib/Data/Static/authorised.json";
+import tooltip from "$lib/Tooltip/tooltip";
+import AnimeRateLimited from "$lib/Error/AnimeRateLimited.svelte";
+import identity from "$stores/identity";
+import SettingHint from "$lib/Settings/SettingHint.svelte";
+import proxy from "$lib/Utility/proxy";
+import { parseScheduleHtml } from "$lib/Data/hololive";
+import type { Preferences } from "../../../graphql/$types";
+import SvelteMarkdown from "@humanspeak/svelte-markdown";
+import MarkdownLink from "$lib/MarkdownLink.svelte";
+import LinkedTooltip from "$lib/Tooltip/LinkedTooltip.svelte";
+import { graphql } from "$houdini";
+import type { PageData } from "./$types";
+
+export let data: PageData;
+
+$: ({ Profile } = data);
+$: preferences = $Profile.fetching
+ ? undefined
+ : ($Profile.data?.User?.preferences as Preferences | undefined);
+$: isOwner = Boolean(userData && userData.id === $identity.id);
+$: ownerPreferences = preferences ?? {
+ created_at: "",
+ updated_at: "",
+ user_id: userData?.id ?? 0,
+ pinned_hololive_streams: [],
+ hide_missing_badges: false,
+ biography: null,
+ badge_wall_css: "",
+ hide_awc_badges: false,
+ pinned_badge_wall_categories: [],
+};
+
+const setCategoriesQuery = graphql(`
mutation SetCategories($categories: [String!]!) {
setPinnedBadgeWallCategories(categories: $categories) {
id
@@ -42,7 +55,7 @@
}
`);
- const toggleCategoryQuery = graphql(`
+const toggleCategoryQuery = graphql(`
mutation ToggleCategory($category: String!) {
togglePinnedBadgeWallCategory(category: $category) {
id
@@ -54,7 +67,7 @@
}
`);
- const toggleHideMissingBadgesQuery = graphql(`
+const toggleHideMissingBadgesQuery = graphql(`
mutation ToggleHideMissingBadges {
toggleHideMissingBadges {
id
@@ -66,7 +79,7 @@
}
`);
- const toggleHideAWCBadgesQuery = graphql(`
+const toggleHideAWCBadgesQuery = graphql(`
mutation ToggleHideAWCBadges {
toggleHideAWCBadges {
id
@@ -78,7 +91,7 @@
}
`);
- const setBiographyQuery = graphql(`
+const setBiographyQuery = graphql(`
mutation SetBiography($biography: String!) {
setBiography(biography: $biography) {
id
@@ -90,7 +103,7 @@
}
`);
- const setBadgeWallCSSQuery = graphql(`
+const setBadgeWallCSSQuery = graphql(`
mutation SetBadgeWallCSS($css: String!) {
setBadgeWallCSS(css: $css) {
id
@@ -102,121 +115,126 @@
}
`);
- $: userData = data.userData;
-
- let error = false;
- let schedule: ParseResult | undefined = undefined;
- let draggedCategory: string | null = null;
- let draggedOverCategory: string | null = null;
-
- $: displayBadges = (username: string, badges: number | string) =>
- $locale({
- values: {
- badges: badges,
- username
- }
- }).user.profile.badges;
-
- const handleDragStart = (
- event: DragEvent & { currentTarget: EventTarget & HTMLDivElement },
- category: string | null
- ) => {
- draggedCategory = category;
-
- if (event.dataTransfer) event.dataTransfer.effectAllowed = 'move';
- };
-
- const handleDragOver = (event: DragEvent) => {
- event.preventDefault();
-
- if (event.dataTransfer) event.dataTransfer.dropEffect = 'move';
- };
-
- const handleDragEnter = (
- event: DragEvent & { currentTarget: EventTarget & HTMLDivElement },
- category: string | null
- ) => {
- event.preventDefault();
-
- if (draggedCategory !== category && preferences && draggedCategory) {
- draggedOverCategory = category;
-
- const categories = preferences.pinned_badge_wall_categories;
- const draggedIndex = categories.indexOf(draggedCategory);
- const targetIndex = categories.indexOf(category || '');
-
- categories.splice(draggedIndex, 1);
- categories.splice(targetIndex, 0, draggedCategory);
-
- preferences.pinned_badge_wall_categories = categories;
- }
- };
-
- const handleDragLeave = (
- event: DragEvent & { currentTarget: EventTarget & HTMLDivElement },
- category: string
- ) => {
- event.preventDefault();
-
- if (draggedOverCategory === category && preferences && draggedCategory) {
- draggedOverCategory = null;
-
- const categories = preferences.pinned_badge_wall_categories;
- const draggedIndex = categories.indexOf(draggedCategory);
-
- categories.splice(draggedIndex, 1);
- categories.splice(categories.indexOf(category) + 1, 0, draggedCategory);
-
- preferences.pinned_badge_wall_categories = categories;
- }
- };
-
- const handleDrop = (event: { preventDefault: () => void }) => {
- event.preventDefault();
-
- if (userData && preferences)
- setCategoriesQuery
- .mutate({
- categories: preferences.pinned_badge_wall_categories
- })
- .then();
-
- draggedCategory = null;
- draggedOverCategory = null;
- };
-
- onMount(async () => {
- schedule = typeSchedule(
- parseScheduleHtml(
- await (
- await fetch(proxy('https://schedule.hololive.tv'), {
- headers: {
- Cookie: 'timezone=Asia/Tokyo'
- }
- })
- ).text()
- )
- );
- });
-
- const getBadgeWallCSS = () =>
- (document.getElementById('badgeWallCSS') as HTMLTextAreaElement).value;
-
- const getBiography = () =>
- (document.getElementById('biography') as HTMLTextAreaElement).value.slice(0, 3000);
-
- const toggleCategory = () => {
- if (!userData) return;
-
- const categoryElement = document.getElementById('category') as HTMLInputElement;
- const category = categoryElement.value;
-
- toggleCategoryQuery.mutate({ category }).then();
-
- categoryElement.value = '';
- };
-
- // 8.5827814569536423841e0
+$: userData = data.userData;
+
+let error = false;
+let schedule: ParseResult | undefined = undefined;
+let draggedCategory: string | null = null;
+let draggedOverCategory: string | null = null;
+
+$: displayBadges = (username: string, badges: number | string) =>
+ $locale({
+ values: {
+ badges: badges,
+ username,
+ },
+ }).user.profile.badges;
+
+const handleDragStart = (
+ event: DragEvent & { currentTarget: EventTarget & HTMLDivElement },
+ category: string | null,
+) => {
+ draggedCategory = category;
+
+ if (event.dataTransfer) event.dataTransfer.effectAllowed = "move";
+};
+
+const handleDragOver = (event: DragEvent) => {
+ event.preventDefault();
+
+ if (event.dataTransfer) event.dataTransfer.dropEffect = "move";
+};
+
+const handleDragEnter = (
+ event: DragEvent & { currentTarget: EventTarget & HTMLDivElement },
+ category: string | null,
+) => {
+ event.preventDefault();
+
+ if (draggedCategory !== category && draggedCategory) {
+ draggedOverCategory = category;
+
+ const categories = ownerPreferences.pinned_badge_wall_categories;
+ const draggedIndex = categories.indexOf(draggedCategory);
+ const targetIndex = categories.indexOf(category || "");
+
+ categories.splice(draggedIndex, 1);
+ categories.splice(targetIndex, 0, draggedCategory);
+
+ ownerPreferences.pinned_badge_wall_categories = categories;
+ }
+};
+
+const handleDragLeave = (
+ event: DragEvent & { currentTarget: EventTarget & HTMLDivElement },
+ category: string,
+) => {
+ event.preventDefault();
+
+ if (draggedOverCategory === category && draggedCategory) {
+ draggedOverCategory = null;
+
+ const categories = ownerPreferences.pinned_badge_wall_categories;
+ const draggedIndex = categories.indexOf(draggedCategory);
+
+ categories.splice(draggedIndex, 1);
+ categories.splice(categories.indexOf(category) + 1, 0, draggedCategory);
+
+ ownerPreferences.pinned_badge_wall_categories = categories;
+ }
+};
+
+const handleDrop = (event: { preventDefault: () => void }) => {
+ event.preventDefault();
+
+ if (userData)
+ setCategoriesQuery
+ .mutate({
+ categories: ownerPreferences.pinned_badge_wall_categories,
+ })
+ .then();
+
+ draggedCategory = null;
+ draggedOverCategory = null;
+};
+
+onMount(async () => {
+ schedule = typeSchedule(
+ parseScheduleHtml(
+ await (
+ await fetch(proxy("https://schedule.hololive.tv"), {
+ headers: {
+ Cookie: "timezone=Asia/Tokyo",
+ },
+ })
+ ).text(),
+ ),
+ );
+});
+
+const getBadgeWallCSS = () =>
+ (document.getElementById("badgeWallCSS") as HTMLTextAreaElement).value;
+
+const getBiography = () =>
+ (document.getElementById("biography") as HTMLTextAreaElement).value.slice(
+ 0,
+ 3000,
+ );
+
+const toggleCategory = () => {
+ if (!userData) return;
+
+ const categoryElement = document.getElementById(
+ "category",
+ ) as HTMLInputElement;
+ const category = categoryElement.value;
+
+ toggleCategoryQuery.mutate({ category }).then();
+
+ categoryElement.value = "";
+};
+
+// 8.5827814569536423841e0
</script>
<HeadTitle route={`${data.username}'s Profile`} path={`/user/${data.username}`} />
@@ -354,7 +372,7 @@
</div>
{/if}
- {#if preferences && userData && userData.id === $identity.id}
+ {#if isOwner}
<Spacer />
<details open>
@@ -365,7 +383,7 @@
onchange={() => {
if (userData) toggleHideMissingBadgesQuery.mutate(null).then();
}}
- checked={preferences.hide_missing_badges}
+ checked={ownerPreferences.hide_missing_badges}
/>
{$locale().user.preferences.hideMissingBadges.title}
<SettingHint lineBreak>{$locale().user.preferences.hideMissingBadges.hint}</SettingHint>
@@ -377,7 +395,7 @@
onchange={() => {
if (userData) toggleHideAWCBadgesQuery.mutate(null).then();
}}
- checked={preferences.hide_awc_badges}
+ checked={ownerPreferences.hide_awc_badges}
/>
{$locale().user.preferences.hideAWCBadges.title}
@@ -386,7 +404,7 @@
Pinned Categories
<div class="pinned-categories">
- {#each preferences.pinned_badge_wall_categories as category}
+ {#each ownerPreferences.pinned_badge_wall_categories as category}
<div
class="card card-small pinned-category"
draggable="true"
@@ -434,7 +452,7 @@
}}>Save</button
>
<textarea
- value={preferences.biography}
+ value={ownerPreferences.biography}
rows="5"
cols="100"
id="biography"
@@ -456,7 +474,7 @@
}}>Save</button
>
<textarea
- value={preferences.badge_wall_css}
+ value={ownerPreferences.badge_wall_css}
rows="10"
cols="100"
id="badgeWallCSS"
diff --git a/src/routes/user/[user]/+page.ts b/src/routes/user/[user]/+page.ts
index ca16077f..6ec3c845 100644
--- a/src/routes/user/[user]/+page.ts
+++ b/src/routes/user/[user]/+page.ts
@@ -1,21 +1,21 @@
-import { load_Profile } from '$houdini';
-import { user } from '$lib/Data/AniList/user';
-import type { LoadEvent } from '@sveltejs/kit';
+import { load_Profile } from "$houdini";
+import { user } from "$lib/Data/AniList/user";
+import type { LoadEvent } from "@sveltejs/kit";
export const load = async (event: LoadEvent) => {
- const username = event.params.user as string;
- const userData = await user(username, /^\d+$/.test(username));
+ const username = event.params.user as string;
+ const userData = await user(username, /^\d+$/.test(username));
- if (!userData) throw new Error(`User not found: ${username}`);
+ if (!userData) throw new Error(`User not found: ${username}`);
- return {
- ...(await load_Profile({
- event,
- variables: {
- id: userData.id
- }
- })),
- username,
- userData
- };
+ return {
+ ...(await load_Profile({
+ event,
+ variables: {
+ id: userData.id,
+ },
+ })),
+ username,
+ userData,
+ };
};
diff --git a/src/routes/user/[user]/badges/+page.gql b/src/routes/user/[user]/badges/+page.gql
index 060b38e7..afdd797d 100644
--- a/src/routes/user/[user]/badges/+page.gql
+++ b/src/routes/user/[user]/badges/+page.gql
@@ -1,31 +1,31 @@
query BadgeWallUser($id: Int!) {
- User(id: $id) {
- id
+ User(id: $id) {
+ id
- badges {
- post
- image
- description
- id
- time
- category
- hidden
- source
- designer
- shadow_hidden
- click_count
- }
+ badges {
+ post
+ image
+ description
+ id
+ time
+ category
+ hidden
+ source
+ designer
+ shadow_hidden
+ click_count
+ }
- preferences {
- created_at
- updated_at
- user_id
- pinned_hololive_streams
- hide_missing_badges
- biography
- badge_wall_css
- hide_awc_badges
- pinned_badge_wall_categories
- }
- }
+ preferences {
+ created_at
+ updated_at
+ user_id
+ pinned_hololive_streams
+ hide_missing_badges
+ biography
+ badge_wall_css
+ hide_awc_badges
+ pinned_badge_wall_categories
+ }
+ }
}
diff --git a/src/routes/user/[user]/badges/+page.svelte b/src/routes/user/[user]/badges/+page.svelte
index 386fe7b1..9ff81118 100644
--- a/src/routes/user/[user]/badges/+page.svelte
+++ b/src/routes/user/[user]/badges/+page.svelte
@@ -1,59 +1,64 @@
<script lang="ts">
- import Spacer from '$lib/Layout/Spacer.svelte';
- import AWC from './../../../../lib/User/BadgeWall/AWC.svelte';
- import { user, type User } from '$lib/Data/AniList/user';
- import type { Badge } from '../../../../graphql/$types';
- import { onDestroy, onMount } from 'svelte';
- import HeadTitle from '$lib/Home/HeadTitle.svelte';
- import { databaseTimeToDate, dateToInputTime, inputTimeToDatabaseTime } from '$lib/Utility/time';
- import proxy from '$lib/Utility/proxy';
- import locale from '$stores/locale';
- import Skeleton from '$lib/Loading/Skeleton.svelte';
- import Message from '$lib/Loading/Message.svelte';
- import Dropdown from '$lib/Layout/Dropdown.svelte';
- import { activityText } from '$lib/Data/AniList/activity';
- import SettingHint from '$lib/Settings/SettingHint.svelte';
- import Popup from '$lib/Layout/Popup.svelte';
- import { page } from '$app/stores';
- import { browser } from '$app/environment';
- import BadgePreview from '$lib/User/BadgeWall/BadgePreview.svelte';
- import authorisedJson from '$lib/Data/Static/authorised.json';
- import identity from '$stores/identity';
- import '$lib/User/BadgeWall/badges.css';
- import Badges from '$lib/User/BadgeWall/Badges.svelte';
- import type { IndexedBadge } from '$lib/User/BadgeWall/badge';
- import { graphql } from '$houdini';
- import type { Preferences } from '../../../../graphql/user/$types';
- import localforage from 'localforage';
-
- export let data;
-
- $: ({ BadgeWallUser } = data);
- $: preferences = $BadgeWallUser.fetching
- ? undefined
- : ($BadgeWallUser.data?.User?.preferences as Preferences | undefined);
-
- $: if (browser && preferences && preferences.badge_wall_css) {
- const sanitise = (css: string) =>
- css
- .replace(/\/\*[\s\S]*?\*\//g, '')
- .replace(/<\/?[^>]+(>|$)/g, '')
- .replace(
- /(expression|javascript|vbscript|onerror|onload|onclick|onmouseover|onmouseout|onmouseup|onmousedown|onkeydown|onkeyup|onkeypress|onblur|onfocus|onsubmit|onreset|onselect|onchange|ondblclick):/gi,
- ''
- )
- .replace(/(behaviour|behavior|moz-binding|content):/gi, '')
- .replace(/\s+/g, ' ')
- .trim();
- const style = document.createElement('style');
-
- style.dataset.badgeWall = 'true';
- style.innerHTML = sanitise(preferences.badge_wall_css);
-
- document.head.appendChild(style);
- }
-
- const updateBadgeQuery = graphql(`
+import Spacer from "$lib/Layout/Spacer.svelte";
+import AWC from "./../../../../lib/User/BadgeWall/AWC.svelte";
+import { user, type User } from "$lib/Data/AniList/user";
+import type { Badge } from "../../../../graphql/$types";
+import { onDestroy, onMount } from "svelte";
+import HeadTitle from "$lib/Home/HeadTitle.svelte";
+import {
+ databaseTimeToDate,
+ dateToInputTime,
+ inputTimeToDatabaseTime,
+} from "$lib/Utility/time";
+import proxy from "$lib/Utility/proxy";
+import locale from "$stores/locale";
+import Skeleton from "$lib/Loading/Skeleton.svelte";
+import Message from "$lib/Loading/Message.svelte";
+import Dropdown from "$lib/Layout/Dropdown.svelte";
+import { activityText } from "$lib/Data/AniList/activity";
+import SettingHint from "$lib/Settings/SettingHint.svelte";
+import Popup from "$lib/Layout/Popup.svelte";
+import { page } from "$app/stores";
+import { browser } from "$app/environment";
+import BadgePreview from "$lib/User/BadgeWall/BadgePreview.svelte";
+import authorisedJson from "$lib/Data/Static/authorised.json";
+import identity from "$stores/identity";
+import "$lib/User/BadgeWall/badges.css";
+import Badges from "$lib/User/BadgeWall/Badges.svelte";
+import type { IndexedBadge } from "$lib/User/BadgeWall/badge";
+import { graphql } from "$houdini";
+import type { Preferences } from "../../../../graphql/$types";
+import localforage from "localforage";
+import type { PageData } from "./$types";
+
+export let data: PageData;
+
+$: ({ BadgeWallUser } = data);
+$: preferences = $BadgeWallUser.fetching
+ ? undefined
+ : ($BadgeWallUser.data?.User?.preferences as Preferences | undefined);
+
+$: if (browser && preferences && preferences.badge_wall_css) {
+ const sanitise = (css: string) =>
+ css
+ .replace(/\/\*[\s\S]*?\*\//g, "")
+ .replace(/<\/?[^>]+(>|$)/g, "")
+ .replace(
+ /(expression|javascript|vbscript|onerror|onload|onclick|onmouseover|onmouseout|onmouseup|onmousedown|onkeydown|onkeyup|onkeypress|onblur|onfocus|onsubmit|onreset|onselect|onchange|ondblclick):/gi,
+ "",
+ )
+ .replace(/(behaviour|behavior|moz-binding|content):/gi, "")
+ .replace(/\s+/g, " ")
+ .trim();
+ const style = document.createElement("style");
+
+ style.dataset.badgeWall = "true";
+ style.innerHTML = sanitise(preferences.badge_wall_css);
+
+ document.head.appendChild(style);
+}
+
+const updateBadgeQuery = graphql(`
mutation UpdateBadge(
$id: Int
$post: String
@@ -95,7 +100,7 @@
}
`);
- const pruneBadgesQuery = graphql(`
+const pruneBadgesQuery = graphql(`
mutation PruneUserBadges {
pruneUserBadges {
id
@@ -117,7 +122,7 @@
}
`);
- const hideCategoryQuery = graphql(`
+const hideCategoryQuery = graphql(`
mutation HideCategory($category: String) {
hideBadge(category: $category) {
id
@@ -139,7 +144,7 @@
}
`);
- const deleteBadgeQuery = graphql(`
+const deleteBadgeQuery = graphql(`
mutation DeleteBadge($id: Int!) {
deleteBadge(id: $id) {
id
@@ -161,7 +166,7 @@
}
`);
- const shadowHideBadgeQuery = graphql(`
+const shadowHideBadgeQuery = graphql(`
mutation ShadowHideBadge($id: Int!, $state: Boolean) {
shadowHideBadge(id: $id, state: $state) {
id
@@ -173,359 +178,387 @@
}
`);
- interface ImportImage {
- link?: string;
- image: string;
- }
-
- let editMode = false;
- let importMode = false;
- let error: null | string;
- let awcPromise: Promise<Response>;
- let confirmDelete = 0;
- let confirmPrune = 0;
- let selectedBadge: IndexedBadge | undefined = undefined;
- let loadError: string | null = null;
- const isId = /^\d+$/.test(data.username);
- let importImages: ImportImage[] | undefined = undefined;
- let importLinks = false;
- let importCategory = '';
- let importReplies = false;
- let badger: Partial<User> | null;
- let migrateMode = false;
- let hideMode = false;
- const authorised = authorisedJson.includes($identity.id);
- let noticeDismissed = false;
-
- $: categoryFilter = new URLSearchParams($page.url.searchParams).get('category');
- $: loadQueryParameter = new URLSearchParams($page.url.searchParams).get('load');
-
- type GroupedBadges = { [key: string]: IndexedBadge[] };
-
- const setShadowHide = () => {
- if (!badger) {
- loadError = 'Something went wrong. Try refreshing.';
-
- return;
- }
-
- shadowHideBadgeQuery.mutate({
- id: badger.id as number
- });
- };
-
- onMount(async () => {
- if (browser && (await localforage.getItem('badgeWallNoticeDismissed'))) noticeDismissed = true;
-
- badger = isId
- ? {
- id: parseInt(data.username),
- name: 'User'
- }
- : await user(data.username);
-
- if (!badger) {
- loadError = "Couldn't find this user.";
-
- return;
- }
-
- awcPromise = fetch(proxy(`https://awc.moe/challenger/${badger.name}`));
- });
-
- onDestroy(() => {
- if (browser)
- Array.from(document.head.querySelectorAll('style')).forEach((style) => {
- if (style.dataset.badgeWall) style.remove();
- });
- });
-
- const submitBadge = () => {
- const imageURL = document.querySelector('input[name="image_url"]') as HTMLInputElement;
- const activityURL = document.querySelector('input[name="activity_url"]') as HTMLInputElement;
- const description = document.querySelector('input[name="description"]') as HTMLInputElement;
- const time = document.querySelector('input[type="datetime-local"]') as HTMLInputElement;
- const category = document.querySelector('input[name="category"]') as HTMLInputElement;
- const hidden = document.querySelector('input[name="hidden"]') as HTMLInputElement;
- const source = document.querySelector('input[name="source"]') as HTMLInputElement;
- const designer = document.querySelector('input[name="designer"]') as HTMLInputElement;
-
- if (!imageURL.value) {
- error = 'Image URL cannot be empty.';
-
- return;
- }
-
- if (
- !imageURL.value.startsWith('http') ||
- (activityURL.value.length > 0 && !activityURL.value.startsWith('http'))
- ) {
- error = 'URLs must start with http or https.';
-
- return;
- }
-
- updateBadgeQuery
- .mutate({
- id: selectedBadge?.id,
- image: imageURL.value,
- post: activityURL.value || '#',
- description: description.value,
- category: category.value,
- time: time.value ? inputTimeToDatabaseTime(new Date(time.value)) : undefined,
- hidden: hidden.value === 'Hidden',
- source: source.value,
- designer: designer.value
- })
- .then(() => {
- error = null;
- imageURL.value = '';
- activityURL.value = '';
- description.value = '';
- category.value = '';
- hidden.value = 'Shown';
- selectedBadge = undefined;
- source.value = '';
- designer.value = '';
- });
- };
-
- const removeAllBadges = () => {
- if (confirmPrune === 2) {
- confirmPrune = 0;
- } else if (confirmPrune === 0) {
- confirmPrune = 1;
-
- return;
- } else {
- confirmPrune = 2;
-
- return;
- }
-
- selectedBadge = undefined;
-
- pruneBadgesQuery.mutate(null).then();
- };
-
- const removeBadge = (badge: Badge) => {
- if (!badge.id) return;
-
- if (confirmDelete === badge.id * 2) {
- confirmDelete = 0;
- } else if (confirmDelete / 4 === badge.id) {
- confirmDelete = badge.id * 2;
-
- return;
- } else {
- confirmDelete = badge.id * 2;
-
- return;
- }
-
- selectedBadge = undefined;
-
- deleteBadgeQuery
- .mutate({
- id: badge.id
- })
- .then();
- };
-
- const groupBadges = (badges: IndexedBadge[]) => {
- const groupedBadges: GroupedBadges = {};
-
- badges.forEach((badge) => {
- if (!badge.category) badge.category = 'Uncategorised';
-
- if (!groupedBadges[badge.category]) groupedBadges[badge.category] = [];
-
- groupedBadges[badge.category].push(badge);
- });
-
- Object.entries(groupedBadges).forEach(([_categoryKey, badges]) => {
- badges.forEach((badge, index) => {
- badge.index = index;
- });
- });
-
- return Object.entries(groupedBadges)
- .sort((a, b) => a[1].length - b[1].length)
- .sort((a, b) => {
- const pinnedCategories =
- preferences && preferences.pinned_badge_wall_categories
- ? preferences.pinned_badge_wall_categories
- : ([] as string[]);
- const aIndex = pinnedCategories.indexOf(a[0]);
- const bIndex = pinnedCategories.indexOf(b[0]);
-
- if (aIndex === -1 && bIndex === -1) return 0;
- if (aIndex === -1) return 1;
- if (bIndex === -1) return -1;
-
- return aIndex - bIndex;
- })
- .reduce((set: GroupedBadges, [key, value]) => {
- set[key] = value;
-
- return set;
- }, {});
- };
-
- const parsePost = async () => {
- if (importImages && importImages.length > 0) importImages = undefined;
-
- const link = (document.querySelector('#import_activity_url') as HTMLInputElement).value;
- const type = link.replace(/.*\/(activity|thread)\/(\d+).*/, '$1');
- const id = link.replace(/.*\/(activity|thread)\/(\d+).*/, '$2');
-
- if (type !== 'activity') return null;
-
- let text = await activityText(parseInt(id), importReplies);
-
- const images: ImportImage[] = [];
-
- if (importLinks) {
- Array.from(new DOMParser().parseFromString(text, 'text/html').querySelectorAll('a')).forEach(
- (a) => {
- const anchor = a as HTMLAnchorElement;
-
- if (anchor.querySelector('img')) {
- images.push({
- link: anchor.href,
- image: (anchor.querySelector('img') as HTMLImageElement).src
- });
- }
- }
- );
-
- text = text.replace(/<a.*?>.*?<img.*?>.*?<\/a>/g, '');
-
- Array.from(
- new DOMParser().parseFromString(text, 'text/html').querySelectorAll('img')
- ).forEach((img) => {
- const image = img as HTMLImageElement;
-
- images.push({
- image: image.src
- });
- });
- } else {
- Array.from(
- new DOMParser().parseFromString(text, 'text/html').querySelectorAll('img')
- ).forEach((img) => {
- const image = img as HTMLImageElement;
-
- images.push({
- image: image.src
- });
- });
- }
-
- importImages = images;
- };
-
- const importBadges = () =>
- fetch(
- `/api/badges?import=true
- ${importCategory.length > 0 ? `&category=${encodeURIComponent(importCategory)}` : ''}
+interface ImportImage {
+ link?: string;
+ image: string;
+}
+
+let editMode = false;
+let importMode = false;
+let error: null | string;
+let awcPromise: Promise<Response>;
+let confirmDelete = 0;
+let confirmPrune = 0;
+let selectedBadge: IndexedBadge | undefined = undefined;
+let loadError: string | null = null;
+const isId = /^\d+$/.test(data.username);
+let importImages: ImportImage[] | undefined = undefined;
+let importLinks = false;
+let importCategory = "";
+let importReplies = false;
+let badger: Partial<User> | null;
+let migrateMode = false;
+let hideMode = false;
+const authorised = authorisedJson.includes($identity.id);
+let noticeDismissed = false;
+
+$: categoryFilter = new URLSearchParams($page.url.searchParams).get("category");
+$: loadQueryParameter = new URLSearchParams($page.url.searchParams).get("load");
+
+type GroupedBadges = { [key: string]: IndexedBadge[] };
+
+const setShadowHide = () => {
+ if (!badger) {
+ loadError = "Something went wrong. Try refreshing.";
+
+ return;
+ }
+
+ shadowHideBadgeQuery.mutate({
+ id: badger.id as number,
+ });
+};
+
+onMount(async () => {
+ if (browser && (await localforage.getItem("badgeWallNoticeDismissed")))
+ noticeDismissed = true;
+
+ badger = isId
+ ? {
+ id: parseInt(data.username),
+ name: "User",
+ }
+ : await user(data.username);
+
+ if (!badger) {
+ loadError = "Couldn't find this user.";
+
+ return;
+ }
+
+ awcPromise = fetch(proxy(`https://awc.moe/challenger/${badger.name}`));
+});
+
+onDestroy(() => {
+ if (browser)
+ Array.from(document.head.querySelectorAll("style")).forEach((style) => {
+ if (style.dataset.badgeWall) style.remove();
+ });
+});
+
+const submitBadge = () => {
+ const imageURL = document.querySelector(
+ 'input[name="image_url"]',
+ ) as HTMLInputElement;
+ const activityURL = document.querySelector(
+ 'input[name="activity_url"]',
+ ) as HTMLInputElement;
+ const description = document.querySelector(
+ 'input[name="description"]',
+ ) as HTMLInputElement;
+ const time = document.querySelector(
+ 'input[type="datetime-local"]',
+ ) as HTMLInputElement;
+ const category = document.querySelector(
+ 'input[name="category"]',
+ ) as HTMLInputElement;
+ const hidden = document.querySelector(
+ 'input[name="hidden"]',
+ ) as HTMLInputElement;
+ const source = document.querySelector(
+ 'input[name="source"]',
+ ) as HTMLInputElement;
+ const designer = document.querySelector(
+ 'input[name="designer"]',
+ ) as HTMLInputElement;
+
+ if (!imageURL.value) {
+ error = "Image URL cannot be empty.";
+
+ return;
+ }
+
+ if (
+ !imageURL.value.startsWith("http") ||
+ (activityURL.value.length > 0 && !activityURL.value.startsWith("http"))
+ ) {
+ error = "URLs must start with http or https.";
+
+ return;
+ }
+
+ updateBadgeQuery
+ .mutate({
+ id: selectedBadge?.id,
+ image: imageURL.value,
+ post: activityURL.value || "#",
+ description: description.value,
+ category: category.value,
+ time: time.value
+ ? inputTimeToDatabaseTime(new Date(time.value))
+ : undefined,
+ hidden: hidden.value === "Hidden",
+ source: source.value,
+ designer: designer.value,
+ })
+ .then(() => {
+ error = null;
+ imageURL.value = "";
+ activityURL.value = "";
+ description.value = "";
+ category.value = "";
+ hidden.value = "Shown";
+ selectedBadge = undefined;
+ source.value = "";
+ designer.value = "";
+ });
+};
+
+const removeAllBadges = () => {
+ if (confirmPrune === 2) {
+ confirmPrune = 0;
+ } else if (confirmPrune === 0) {
+ confirmPrune = 1;
+
+ return;
+ } else {
+ confirmPrune = 2;
+
+ return;
+ }
+
+ selectedBadge = undefined;
+
+ pruneBadgesQuery.mutate(null).then();
+};
+
+const removeBadge = (badge: Badge) => {
+ if (!badge.id) return;
+
+ if (confirmDelete === badge.id * 2) {
+ confirmDelete = 0;
+ } else if (confirmDelete / 4 === badge.id) {
+ confirmDelete = badge.id * 2;
+
+ return;
+ } else {
+ confirmDelete = badge.id * 2;
+
+ return;
+ }
+
+ selectedBadge = undefined;
+
+ deleteBadgeQuery
+ .mutate({
+ id: badge.id,
+ })
+ .then();
+};
+
+const groupBadges = (badges: IndexedBadge[]) => {
+ const groupedBadges: GroupedBadges = {};
+
+ badges.forEach((badge) => {
+ if (!badge.category) badge.category = "Uncategorised";
+
+ if (!groupedBadges[badge.category]) groupedBadges[badge.category] = [];
+
+ groupedBadges[badge.category].push(badge);
+ });
+
+ Object.entries(groupedBadges).forEach(([_categoryKey, badges]) => {
+ badges.forEach((badge, index) => {
+ badge.index = index;
+ });
+ });
+
+ return Object.entries(groupedBadges)
+ .sort((a, b) => a[1].length - b[1].length)
+ .sort((a, b) => {
+ const pinnedCategories =
+ preferences && preferences.pinned_badge_wall_categories
+ ? preferences.pinned_badge_wall_categories
+ : ([] as string[]);
+ const aIndex = pinnedCategories.indexOf(a[0]);
+ const bIndex = pinnedCategories.indexOf(b[0]);
+
+ if (aIndex === -1 && bIndex === -1) return 0;
+ if (aIndex === -1) return 1;
+ if (bIndex === -1) return -1;
+
+ return aIndex - bIndex;
+ })
+ .reduce((set: GroupedBadges, [key, value]) => {
+ set[key] = value;
+
+ return set;
+ }, {});
+};
+
+const parsePost = async () => {
+ if (importImages && importImages.length > 0) importImages = undefined;
+
+ const link = (
+ document.querySelector("#import_activity_url") as HTMLInputElement
+ ).value;
+ const type = link.replace(/.*\/(activity|thread)\/(\d+).*/, "$1");
+ const id = link.replace(/.*\/(activity|thread)\/(\d+).*/, "$2");
+
+ if (type !== "activity") return null;
+
+ let text = await activityText(parseInt(id), importReplies);
+
+ const images: ImportImage[] = [];
+
+ if (importLinks) {
+ Array.from(
+ new DOMParser().parseFromString(text, "text/html").querySelectorAll("a"),
+ ).forEach((a) => {
+ const anchor = a as HTMLAnchorElement;
+
+ if (anchor.querySelector("img")) {
+ images.push({
+ link: anchor.href,
+ image: (anchor.querySelector("img") as HTMLImageElement).src,
+ });
+ }
+ });
+
+ text = text.replace(/<a.*?>.*?<img.*?>.*?<\/a>/g, "");
+
+ Array.from(
+ new DOMParser()
+ .parseFromString(text, "text/html")
+ .querySelectorAll("img"),
+ ).forEach((img) => {
+ const image = img as HTMLImageElement;
+
+ images.push({
+ image: image.src,
+ });
+ });
+ } else {
+ Array.from(
+ new DOMParser()
+ .parseFromString(text, "text/html")
+ .querySelectorAll("img"),
+ ).forEach((img) => {
+ const image = img as HTMLImageElement;
+
+ images.push({
+ image: image.src,
+ });
+ });
+ }
+
+ importImages = images;
+};
+
+const importBadges = () =>
+ fetch(
+ `/api/badges?import=true
+ ${importCategory.length > 0 ? `&category=${encodeURIComponent(importCategory)}` : ""}
`,
- {
- method: 'PUT',
- headers: {
- 'Content-Type': 'application/json'
- },
- body: JSON.stringify(
- importImages?.map((image) => ({
- image: image.image,
- post: image.link || '#',
- category: importCategory
- }))
- )
- }
- ).then(() => {
- importMode = false;
- importImages = undefined;
- });
-
- const migrateCategory = () => {
- fetch(
- `/api/badges?migrate=true&original=${encodeURIComponent(
- (document.querySelector('#migrate_original') as HTMLInputElement).value
- )}&new=${encodeURIComponent(
- (document.querySelector('#migrate_new') as HTMLInputElement).value
- )}`,
- {
- method: 'PUT'
- }
- ).then(() => (migrateMode = false));
- };
-
- const hideCategory = () => {
- hideCategoryQuery
- .mutate({
- category: (document.querySelector('#category_hide') as HTMLInputElement).value
- })
- .then(() => (hideMode = false));
- };
-
- const removeHiddenBadges = (isOwner: boolean, badges: IndexedBadge[]) =>
- isOwner || authorised ? badges : badges.filter((b) => !b.hidden && !b.shadow_hidden);
-
- const setAdjacentCursor = (badges: IndexedBadge[], direction: number) => {
- const currentCategory = selectedBadge?.category || 'Uncategorised';
- const currentBadge = selectedBadge?.index;
- const categoryBadges = groupBadges(badges)[currentCategory];
-
- if (!currentCategory || currentBadge === undefined) return;
-
- let previousBadge = categoryBadges[currentBadge + direction];
-
- while (previousBadge && (previousBadge.hidden || previousBadge.shadow_hidden))
- previousBadge = categoryBadges[previousBadge.index + direction];
-
- if (previousBadge) selectedBadge = previousBadge;
- };
-
- const adjacentBadgeExists = (
- selectedBadge: IndexedBadge | undefined,
- badges: IndexedBadge[],
- direction: number
- ) => {
- const currentCategory = selectedBadge?.category || 'Uncategorised';
- const currentBadge = selectedBadge?.index;
- const categoryBadges = groupBadges(badges)[currentCategory];
-
- if (!currentCategory || currentBadge === undefined || !categoryBadges) return;
-
- let previousBadge = categoryBadges[currentBadge + direction];
-
- while (previousBadge && (previousBadge.hidden || previousBadge.shadow_hidden))
- previousBadge = categoryBadges[previousBadge.index + direction];
-
- return previousBadge;
- };
-
- const castAsStringArray = (array: unknown[]) => array as string[];
-
- const castBadgesToIndexedBadges = (array: unknown[]) => array as IndexedBadge[];
-
- const shadowHideBadge = () => {
- if (!selectedBadge && !authorised) return;
-
- if (!badger) {
- loadError = 'Something went wrong. Try refreshing.';
-
- return;
- }
-
- shadowHideBadgeQuery
- .mutate({
- id: badger.id as number,
- state: selectedBadge?.shadow_hidden as boolean
- })
- .then();
- };
+ {
+ method: "PUT",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ body: JSON.stringify(
+ importImages?.map((image) => ({
+ image: image.image,
+ post: image.link || "#",
+ category: importCategory,
+ })),
+ ),
+ },
+ ).then(() => {
+ importMode = false;
+ importImages = undefined;
+ });
+
+const migrateCategory = () => {
+ fetch(
+ `/api/badges?migrate=true&original=${encodeURIComponent(
+ (document.querySelector("#migrate_original") as HTMLInputElement).value,
+ )}&new=${encodeURIComponent(
+ (document.querySelector("#migrate_new") as HTMLInputElement).value,
+ )}`,
+ {
+ method: "PUT",
+ },
+ ).then(() => (migrateMode = false));
+};
+
+const hideCategory = () => {
+ hideCategoryQuery
+ .mutate({
+ category: (document.querySelector("#category_hide") as HTMLInputElement)
+ .value,
+ })
+ .then(() => (hideMode = false));
+};
+
+const removeHiddenBadges = (isOwner: boolean, badges: IndexedBadge[]) =>
+ isOwner || authorised
+ ? badges
+ : badges.filter((b) => !b.hidden && !b.shadow_hidden);
+
+const setAdjacentCursor = (badges: IndexedBadge[], direction: number) => {
+ const currentCategory = selectedBadge?.category || "Uncategorised";
+ const currentBadge = selectedBadge?.index;
+ const categoryBadges = groupBadges(badges)[currentCategory];
+
+ if (!currentCategory || currentBadge === undefined) return;
+
+ let previousBadge = categoryBadges[currentBadge + direction];
+
+ while (previousBadge && (previousBadge.hidden || previousBadge.shadow_hidden))
+ previousBadge = categoryBadges[previousBadge.index + direction];
+
+ if (previousBadge) selectedBadge = previousBadge;
+};
+
+const adjacentBadgeExists = (
+ selectedBadge: IndexedBadge | undefined,
+ badges: IndexedBadge[],
+ direction: number,
+) => {
+ const currentCategory = selectedBadge?.category || "Uncategorised";
+ const currentBadge = selectedBadge?.index;
+ const categoryBadges = groupBadges(badges)[currentCategory];
+
+ if (!currentCategory || currentBadge === undefined || !categoryBadges) return;
+
+ let previousBadge = categoryBadges[currentBadge + direction];
+
+ while (previousBadge && (previousBadge.hidden || previousBadge.shadow_hidden))
+ previousBadge = categoryBadges[previousBadge.index + direction];
+
+ return previousBadge;
+};
+
+const castAsStringArray = (array: unknown[]) => array as string[];
+
+const castBadgesToIndexedBadges = (array: unknown[]) => array as IndexedBadge[];
+
+const shadowHideBadge = () => {
+ if (!selectedBadge && !authorised) return;
+
+ if (!badger) {
+ loadError = "Something went wrong. Try refreshing.";
+
+ return;
+ }
+
+ shadowHideBadgeQuery
+ .mutate({
+ id: badger.id as number,
+ state: selectedBadge?.shadow_hidden as boolean,
+ })
+ .then();
+};
</script>
<HeadTitle route={`${data.username}'s Badge Wall`} path={`/user/${data.username}`} />
@@ -580,7 +613,7 @@
be required to use the hide feature to hide these badges from the public, while allowing
them to stay visible to you as the account holder.
</div>
- {:else if !noticeDismissed}
+ {:else if false && !noticeDismissed}
<div class="card">
<b>Notice:</b> AniList has begun purging outbound links which contain AI-generated
material, this includes Badge Wall. If you have collected badges with AI-generated
diff --git a/src/routes/user/[user]/badges/+page.ts b/src/routes/user/[user]/badges/+page.ts
index db70d16c..a14c0a6a 100644
--- a/src/routes/user/[user]/badges/+page.ts
+++ b/src/routes/user/[user]/badges/+page.ts
@@ -1,22 +1,22 @@
-import { load_BadgeWallUser } from '$houdini';
-import { user } from '$lib/Data/AniList/user';
-import type { LoadEvent } from '@sveltejs/kit';
+import { load_BadgeWallUser } from "$houdini";
+import { user } from "$lib/Data/AniList/user";
+import type { LoadEvent } from "@sveltejs/kit";
export const load = async (event: LoadEvent) => {
- const username = event.params.user as string;
- const userData = await user(username, /^\d+$/.test(username));
+ const username = event.params.user as string;
+ const userData = await user(username, /^\d+$/.test(username));
- if (!userData) throw new Error(`User not found: ${username}`);
+ if (!userData) throw new Error(`User not found: ${username}`);
- return {
- ...(await load_BadgeWallUser({
- event,
- variables: {
- id: userData.id
- }
- })),
- username,
- userData,
- event
- };
+ return {
+ ...(await load_BadgeWallUser({
+ event,
+ variables: {
+ id: userData.id,
+ },
+ })),
+ username,
+ userData,
+ event,
+ };
};